package com.mz.ieann.doplayer.audio.core.impl.media

import android.content.Context
import android.media.MediaPlayer
import android.media.audiofx.BassBoost
import android.media.audiofx.Equalizer
import android.media.audiofx.PresetReverb
import android.media.audiofx.Visualizer
import android.util.Log
import android.view.LayoutInflater
import android.view.ViewGroup
import android.widget.LinearLayout
import android.widget.RelativeLayout
import android.widget.SeekBar
import android.widget.SeekBar.OnSeekBarChangeListener
import android.widget.TextView
import androidx.core.content.ContextCompat
import com.mz.ieann.doplayer.R
import com.mz.ieann.doplayer.audio.listener.ProgressListener
import com.mz.ieann.doplayer.audio.widget.YouVisualizerView

/**
 * <p>------------------------------------------------------
 * <p>Copyright (C) 2020 wasu company, All rights reserved.
 * <p>------------------------------------------------------
 * <p> 添加音谱，均衡器，重低音UI
 * <p>
 *
 * @author Created by zhangmz
 * @date on 2023/5/22
 */
class MediaEffectsUtil(
    private val TAG: String,
    private val player: MediaPlayer,
    private val visualizerView: YouVisualizerView? = null
) {

    /**
     * 系统音谱
     */
    private var visualizer: Visualizer? = null

    /**
     * 初始化系统音谱
     */
    fun setupVisualizer(
        progressListener: ProgressListener?
    ): MediaEffectsUtil {
        if (visualizerView == null && progressListener == null){
            return this
        }
        val audioSessionId = player.audioSessionId
        visualizer = Visualizer(audioSessionId)
        // 采样长度，即回调方法中ByteArray的size，[0]=0;[1]=1024
        visualizer?.captureSize = Visualizer.getCaptureSizeRange()[1]
        // 采样频率, Visualizer.getMaxCaptureRate()=20000HZ 返回最大采样频率
        // 数值越小，采样率越低，回调的方法 onWaveFormDataCapture 或者 onFftDataCapture 间隔越大，刷新越慢
        val captureRate = Visualizer.getMaxCaptureRate() / 2
        // 波形信号
        val waveform = true
        // 频域信号, Fast Fourier Transformation,傅里叶算法快速转化,它用于把时域上连续的信号(波形)强度转换成离散的频域信号(频谱)
        val fft = false
        Log.v(TAG, "setupVisualizer, audioSessionId:$audioSessionId; captureRate:$captureRate; captureSize:${visualizer?.captureSize}")
        /**
         * onFftDataCapture 和 onWaveFormDataCapture回调说明
         */
        visualizer?.setDataCaptureListener(object : Visualizer.OnDataCaptureListener {
            // waveform:true;fft=false 时回调
            override fun onWaveFormDataCapture(
                visualizer: Visualizer?,
                // 波形采样的字节数组，它包含一系列的8位（无符号）的PCM单声道样本，长度1024，大小-128-127之间
                waveform: ByteArray?,
                samplingRate: Int
            ) {
                progressListener?.updateProgress(player.duration, player.currentPosition)
                visualizerView?.updateVisualizer(waveform)
            }
            // waveform:false;fft=true 时回调
            override fun onFftDataCapture(
                visualizer: Visualizer?,
                // 快速傅里叶变化采样数组
                // 回调 fft.size应该=1024，是由实数和虚数组成
                fft: ByteArray?,
                samplingRate: Int
            ) {
                progressListener?.updateProgress(player.duration, player.currentPosition)
                visualizerView?.updateVisualizer(fft)
            }
        }, captureRate, waveform, fft)
        // 这是默认的Visualizer模式，适用于音乐可视化
        visualizer?.scalingMode = Visualizer.SCALING_MODE_NORMALIZED
        visualizer?.enabled = true
        return this
    }

    /**
     * 系统均衡器
     */
    private var equalizer: Equalizer? = null

    /**
     * 初始化系统均衡器
     */
    fun setupEqualizer(
        context: Context,
        container: ViewGroup? = null
    ): MediaEffectsUtil {
        if (container == null){
            return this
        }
        // 使用audioSessionId创建均衡器，设置Equalizer来控制player，并启用均衡效果
        equalizer = Equalizer(0, player.audioSessionId).apply { enabled = true }

        val minLevel = equalizer?.bandLevelRange?.get(0)?: 0
        val maxLevel = equalizer?.bandLevelRange?.get(1)?: 0
        val brands: Short = equalizer?.numberOfBands?: 0
        Log.v(TAG, "setupEqualizer minLevel:$minLevel; maxLevel:$maxLevel; brands:$brands")

        val bootLayout = LinearLayout(context)
        bootLayout.orientation = LinearLayout.VERTICAL
        bootLayout.layoutParams = ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)

        val progressLayout = LinearLayout(context)
        progressLayout.orientation = LinearLayout.VERTICAL
        progressLayout.layoutParams = ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)

        for (i: Int in 0 until brands) {
            val progressView = LayoutInflater.from(context).inflate(R.layout.dialog_audio_progress_layout, null)
            val seekbar = progressView.findViewById<SeekBar>(R.id.progressBar)
            seekbar.max = maxLevel - minLevel
            seekbar.progress = equalizer?.getBandLevel(i.toShort())?.toInt()?: 0

            Log.v(TAG, "onProgressChanged, seekbar max:${seekbar.max} progress:${seekbar.progress}")
            seekbar.setOnSeekBarChangeListener(object : OnSeekBarChangeListener {
                override fun onProgressChanged(
                    seekBar: SeekBar?,
                    progress: Int,
                    fromUser: Boolean
                ) {
                    Log.v(TAG, "onProgressChanged, index:$i progress:$progress")
                    equalizer?.setBandLevel(i.toShort(), (progress + minLevel).toShort())
                }
                override fun onStartTrackingTouch(seekBar: SeekBar?) {  }
                override fun onStopTrackingTouch(seekBar: SeekBar?) {  }
            })
            val progressText = progressView.findViewById<TextView>(R.id.progressText)
            progressText.text = "${(equalizer?.getCenterFreq(i.toShort())?: 0).toInt() / 1000} Hz"

            progressLayout.addView(progressView)
        }
        bootLayout.addView(progressLayout)

        val numericalLayout = RelativeLayout(context)
        numericalLayout.layoutParams = RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT).apply {
            setMargins(context.resources.getDimensionPixelSize(R.dimen.dp_20), 0, context.resources.getDimensionPixelSize(R.dimen.dp_10), 0)
        }

        val textMin = TextView(context)
        textMin.layoutParams = RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT).apply {
            addRule(RelativeLayout.ALIGN_PARENT_START)
        }
        textMin.setTextColor(ContextCompat.getColor(context, R.color.color_white_FFFFFFFF))
        textMin.textSize = 15.0f
        textMin.text = "${minLevel / 100} Hz"

        val textZero = TextView(context)
        textZero.layoutParams = RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT).apply {
            addRule(RelativeLayout.CENTER_IN_PARENT)
        }
        textZero.setTextColor(ContextCompat.getColor(context, R.color.color_white_FFFFFFFF))
        textZero.textSize = 15.0f
        textZero.text = "0"

        val textMax = TextView(context)
        textMax.layoutParams = RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT).apply {
            addRule(RelativeLayout.ALIGN_PARENT_END)
        }
        textMax.setTextColor(ContextCompat.getColor(context, R.color.color_white_FFFFFFFF))
        textMax.textSize = 15.0f
        textMax.text = "${maxLevel / 100} Hz"

        numericalLayout.addView(textMin)
        numericalLayout.addView(textZero)
        numericalLayout.addView(textMax)
        bootLayout.addView(numericalLayout)

        container.addView(bootLayout)
        return this
    }

    /**
     * 重低音控制器
     */
    private var bass: BassBoost? = null

    /**
     * 初始化重低音控制器
     */
    fun setupBassBoost(
        context: Context,
        container: ViewGroup? = null
    ): MediaEffectsUtil {
        bass = BassBoost(0, player.audioSessionId).apply { enabled = true }
        val progressView = LayoutInflater.from(context).inflate(R.layout.dialog_audio_progress_layout, null)
        val progressText = progressView.findViewById<TextView>(R.id.progressText)
        progressText.text = "重低音"
        val seekbar = progressView.findViewById<SeekBar>(R.id.progressBar)
        seekbar.max = 1000
        seekbar.progress = 0
        seekbar.setOnSeekBarChangeListener(object : OnSeekBarChangeListener {
            override fun onProgressChanged(seekBar: SeekBar?, progress: Int, fromUser: Boolean) {
                bass?.setStrength(progress.toShort())
            }
            override fun onStartTrackingTouch(seekBar: SeekBar?) {  }
            override fun onStopTrackingTouch(seekBar: SeekBar?) {  }
        })
        container?.addView(progressView)
        return this
    }

    /**
     * 音场控制器
     */
    private var presetReverb: PresetReverb? = null

    /**
     * 预设音场控制
     */
    fun setupPresetReverb(
        context: Context,
        container: ViewGroup? = null
    ): MediaEffectsUtil {

        presetReverb = PresetReverb(0, player.audioSessionId).apply { enabled = true }

        val length: Short = equalizer?.numberOfPresets?: 0
        val reverbName = ArrayList<String>(length.toInt())
        Log.v(TAG, "setupPresetReverb, length:$length; reverbName:${reverbName.size}")
        for (i in 0 until length){
            Log.v(TAG, "setupPresetReverb, index:$i name:${equalizer?.getPresetName(i.toShort())}")
        }

        return this
    }

    /**
     * 释放所有控制器
     */
    fun release(){
        visualizer?.enabled = false
        visualizer?.release()

        equalizer?.enabled = false
        equalizer?.release()

        bass?.enabled = false
        bass?.release()

        presetReverb?.enabled = false
        presetReverb?.release()
    }
}